package com.bp.web.system;

import com.bp.common.annotation.Log;
import com.bp.common.config.GlobalConfig;
import com.bp.common.constant.Constants;
import com.bp.common.constant.HttpStatus;
import com.bp.common.core.controller.BaseController;
import com.bp.common.core.domain.AjaxResult;
import com.bp.common.core.page.TableDataInfo;
import com.bp.common.enums.EnumBusinessType;
import com.bp.common.exception.CustomException;
import com.bp.common.utils.StringUtils;
import com.bp.common.utils.file.FileUtils;
import com.bp.common.utils.file.MimeTypeUtils;
import com.bp.common.utils.poi.ExcelUtil;
import com.bp.framework.config.ServerConfig;
import com.bp.framework.util.SecurityUtils;
import com.bp.system.domain.LoginUser;
import com.bp.system.domain.SysFileDomain;
import com.bp.system.domain.SysFileIndex;
import com.bp.system.service.ISysFileService;
import com.bp.system.service.ISysUserService;
import com.bp.system.service.ISysFileIndexService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 文件存储Controller
 *
 * @author shaominjie
 * @date 2021-01-13
 */
@RestController
@RequestMapping("/system/file")
public class SysFileController extends BaseController {
    protected final Logger log = LoggerFactory.getLogger(SysFileController.class);
    @Resource
    private ISysFileService sysFileService;
    @Resource
    private ISysFileIndexService fileIndexService;
    @Resource
    private ISysUserService userService;
    @Resource
    private ServerConfig serverConfig;
    //<editor-fold desc="文件">
    /**
     * 查询文件存储列表
     */
//    @PreAuthorize("@ss.hasPermi('system:file:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysFileDomain sysFileDomain, Integer withChild) {
        startPage();
        if(sysFileDomain.getIndexId() == null){
            return getDataTable(new ArrayList<>());
        }
        Map<String,String> userMap = userService.userName2NickName();
        List<SysFileDomain> list;
        if(withChild == null || withChild == 0){
            list = sysFileService.selectListWithChild(sysFileDomain);
        }else{
            list = sysFileService.selectList(sysFileDomain);
        }
        list.forEach(e -> {
            e.setUserName(userMap.get(e.getCreateBy()));
        });
        return getDataTable(list);
    }

    /**
     * 导出文件存储列表
     */
//    @PreAuthorize("@ss.hasPermi('system:file:export')")
    @Log(title = "文件存储", businessType = EnumBusinessType.EXPORT)
    @GetMapping("/export")
    public AjaxResult export(SysFileDomain sysFileDomain) {
        List<SysFileDomain> list = sysFileService.selectList(sysFileDomain);
        ExcelUtil<SysFileDomain> util = new ExcelUtil<SysFileDomain>(SysFileDomain.class);
        return util.exportExcel(list, "file");
    }

    /**
     * 获取文件存储详细信息
     */
//    @PreAuthorize("@ss.hasPermi('system:file:query')")
    @GetMapping(value = "/{fileId}")
    public AjaxResult getInfo(@PathVariable("fileId") Long fileId) {
        AjaxResult result;
        SysFileDomain file = sysFileService.selectById(fileId);
        if(file != null) {
            result = AjaxResult.success(file);
            SysFileIndex fileIndex = fileIndexService.selectById(file.getIndexId());
            String path = Constants.RESOURCE_PREFIX+fileIndex.getFilePath();
            result.put("filePath",serverConfig.getUrl() + path+"/"+file.getFileName() );
        }else{
            result = AjaxResult.error("文件不存在");
        }


        return result;
    }

    /**
     * 新增文件存储
     */
//    @PreAuthorize("@ss.hasPermi('system:file:add')")
    @Log(title = "文件存储", businessType = EnumBusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SysFileDomain sysFileDomain) {
        return toAjax(sysFileService.insert(sysFileDomain));
    }

    /**
     * 修改文件存储
     */
//    @PreAuthorize("@ss.hasPermi('system:file:edit')")
    @Log(title = "文件存储", businessType = EnumBusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysFileDomain sysFileDomain) {
        return toAjax(sysFileService.update(sysFileDomain));
    }

    /**
     * 删除文件存储
     */
//    @PreAuthorize("@ss.hasPermi('system:file:remove')")
    @Log(title = "文件存储", businessType = EnumBusinessType.DELETE)
    @DeleteMapping("/{fileIds}")
    public AjaxResult remove(@PathVariable Long[] fileIds) {
        return toAjax(sysFileService.deleteByIds(fileIds));
    }
    //</editor-fold>


    @GetMapping(value = "/indexes")
    public AjaxResult fileIndex(){
        LoginUser user = SecurityUtils.getLoginUser();
        if(user == null) {
            throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
        List<SysFileIndex> list = fileIndexService.selectByUserId(user.getUser().getUserId());
        return AjaxResult.success(fileIndexService.buildTree(list));
    }
    @PostMapping(value = "/addIndex")
    public AjaxResult addIndex(@RequestBody SysFileIndex fileIndex) {
        LoginUser user = SecurityUtils.getLoginUser();
        if(user == null) {
            throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
        fileIndex.setUserId(user.getUser().getUserId());
        if(fileIndex.getParentId() != null) {
            List<SysFileIndex> childList =  fileIndexService.selectByParentId(fileIndex.getParentId());
            if(CollectionUtils.isNotEmpty(childList)){
                for(SysFileIndex item: childList){
                    if(item.getIndexName().equals(fileIndex.getIndexName())){
                        throw new CustomException("文件名重复");
                    }
                }
            }
            SysFileIndex parent = fileIndexService.selectById(fileIndex.getParentId());
            fileIndex.setFilePath(parent.getFilePath()+"/" + fileIndex.getIndexName());
        }else{
            fileIndex.setFilePath("/"+user.getUser().getUserName()+"/"+fileIndex.getIndexName());
        }
        File newFile = new File(fileIndex.getFilePath()+"/readme.txt");
        if (!newFile.getParentFile().exists()) {
            newFile.getParentFile().mkdirs();
        }
        return toAjax(fileIndexService.insert(fileIndex));
    }
    @GetMapping(value = "/getIndex/{indexId}")
    public AjaxResult getIndex(@PathVariable(value = "indexId") Long indexId) {
        return AjaxResult.success(fileIndexService.selectById(indexId));
    }
    @GetMapping(value = "/delIndex/{indexId}")
    public AjaxResult delIndex(@PathVariable(value = "indexId") Long indexId) {
        SysFileIndex index = fileIndexService.selectById(indexId);
        if(index == null || index.getIndexId() == null) {
            throw new CustomException("目录已删除");
        }
        if(index.getSystemFlag().equals(0)){
            throw new CustomException("系统目录不可删除");
        }
        List<SysFileIndex> childList =  fileIndexService.selectByParentId(indexId);
        if(CollectionUtils.isNotEmpty(childList)){
            throw new CustomException("存在下级目录，请先删除！");
        }
        List<SysFileDomain> fileList = sysFileService.selectByIndexId(indexId);
        if(CollectionUtils.isNotEmpty(fileList)){
            throw new CustomException("当前目录下有文件存在，请先删除！");
        }
        return AjaxResult.success(fileIndexService.deleteById(indexId));
    }
    @PostMapping(value = "/modifyIndex")
    public AjaxResult modifyIndex(@RequestBody SysFileIndex fileIndex) {
        LoginUser user = SecurityUtils.getLoginUser();
        if(user == null) {
            throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
        if(fileIndex.getParentId() != null) {
            List<SysFileIndex> childList =  fileIndexService.selectByParentId(fileIndex.getParentId());
            if(CollectionUtils.isNotEmpty(childList)){
                for(SysFileIndex item: childList){
                    if(item.getIndexName().equals(fileIndex.getIndexName()) && !item.getIndexId().equals(fileIndex.getIndexId())){
                        throw new CustomException("文件名重复");
                    }
                }
            }
        }
        return toAjax(fileIndexService.update(fileIndex));
    }

    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file,Long indexId) throws Exception {
        LoginUser user = SecurityUtils.getLoginUser();
        if(user == null) {
            throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
        SysFileIndex fileIndex = fileIndexService.selectById(indexId);
        if(fileIndex == null || fileIndex.getIndexId() == null){
            throw new CustomException("目录不存在");
        }

        try {
            // 暂不允许同目录下同名文件存在
            SysFileDomain fileDb = sysFileService.selectByFileName(fileIndex.getIndexId(),file.getOriginalFilename());
            if(fileDb !=null && fileDb.getFileId() != null) {
                throw new CustomException("存在同名文件");
            }

            // 上传文件路径 fileIndex.getFilePath()
            // 上传并返回新文件名称
            String fileName = sysFileService.upload(fileIndex.getFilePath(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);

            // 数据保存数据库
            SysFileDomain fileDomain = new SysFileDomain();
            fileDomain.setIndexId(fileIndex.getIndexId());
            fileDomain.setFileName(file.getOriginalFilename());
            fileDomain.setFileSize(file.getSize());
            fileDomain.setFilePath(fileIndex.getFilePath()+"/"+file.getOriginalFilename());
            String url = serverConfig.getUrl() + fileDomain.getFilePath();
            fileDomain.setCreateTime(new Date());
            fileDomain.setCreateBy(user.getUsername());
            sysFileService.insert(fileDomain);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", fileName);
            ajax.put("url", url);
            ajax.put("file", fileDomain);
            return ajax;
        }
        catch (Exception e) {
            throw new CustomException(e.getMessage());
        }
    }
    @GetMapping("/getFile/{indexId}/{fileId}")
    public AjaxResult getFile(@PathVariable("indexId")Long indexId, @PathVariable(value = "fileId",required = false) Long fileId) throws Exception {
        AjaxResult result =AjaxResult.success();
        SysFileIndex fileIndex = fileIndexService.selectById(indexId);
        if(fileId != null){
            String path = Constants.RESOURCE_PREFIX+fileIndex.getFilePath();
            result.put("filePath",serverConfig.getUrl()+ path+"/"+fileIndex.getIndexName() );
        }else{

        }
        return result;
    }
    @GetMapping("/download/{fileId}")
    public void fileDownload(@PathVariable(value = "fileId")Long fileId,  HttpServletResponse response, HttpServletRequest request) {
        try {
            // 默认查询对应文件
            SysFileDomain file = sysFileService.selectById(fileId);
            SysFileIndex fileIndex = fileIndexService.selectById(file.getIndexId());
            String realFileName =file.getFileName() ;
            if (!FileUtils.isValidFilename(file.getFileName())) {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", realFileName));
            }
            String filePath = GlobalConfig.getProfile()+fileIndex.getFilePath()+"/" + realFileName;

            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
            FileUtils.writeBytes(filePath, response.getOutputStream());
        }
        catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }
    /**
     * 获取区域下拉树列表
     */
    @GetMapping("/index/treeSelect")
    public AjaxResult treeSelect(SysFileIndex fileIndex) {
        Long userId = SecurityUtils.getUserId();
        fileIndex.setUserId(userId);
        List<SysFileIndex> fileIndexList = fileIndexService.selectList(fileIndex);
        return AjaxResult.success(fileIndexService.buildTree(fileIndexList));
    }

    @GetMapping("/getFiles")
    public AjaxResult getFiles(String fileIds) {

        List<AjaxResult> list = new ArrayList<>();
        List<SysFileDomain> fileDomains = sysFileService.selectByIds(fileIds);
        if(CollectionUtils.isNotEmpty(fileDomains)){
            for (SysFileDomain item : fileDomains){
                AjaxResult ajax = AjaxResult.success();
                ajax.put("fileName", item.getFileName());
                ajax.put("url",  serverConfig.getUrl() + item.getFilePath());
                ajax.put("file", item);
                list.add(ajax);
            }
        }
        return AjaxResult.success(list);
    }
}